/*
 Developer: John Archer (john.archer.jpa@gmail.com)
 
 This file is part of VTBuilder.

 VTBuilder is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License.

 VTBuilder is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with VTBuilder.  If not, see <http://www.gnu.org/licenses/>.
 */
package core.tasks;

import core.para.Para;
import core.sb.SB;
import core.sb.s.Seq;
import core.tasks.pack.SPartPack;
import gui.processor.Processor;
import gui.utils.ProgBar;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class SPart {

    public SPart() {
    }

    public ArrayList<SB> sPart(ArrayList<Seq> rin, Processor p, double kt) throws Exception {
        ArrayList<SB> fBins = new ArrayList<SB>();
        CountDownLatch cdl;
        ArrayList<Seq> reads = new ArrayList<Seq>();
        HashMap<String, ArrayList<Integer>> hash = new HashMap<String, ArrayList<Integer>>(250);
        Seq initSeed;
        ArrayList<Seq> bin;

        DecimalFormat df = null;
        int startSize = rin.size();
        if (Para.GUI) {
            p.dPrgA(ProgBar.START, startSize);
        } else {
            df = new DecimalFormat("##.##");
        }

        do {
            initSeed = rin.remove(0);
            bin = new ArrayList<Seq>();
            bin.add(initSeed);
            String dna = initSeed.dna;
            int size = rin.size() / Para.TRDS;
            hash.clear();
            for (int loc = 0; loc < (dna.length() - 10); loc++) {
                if (hash.containsKey(dna.substring(loc, loc + 10))) {
                    hash.get(dna.substring(loc, loc + 10)).add(loc);
                } else {
                    hash.put(dna.substring(loc, loc + 10), new ArrayList<Integer>(Arrays.asList(loc)));
                }
            }

            cdl = new CountDownLatch(Para.TRDS);
            ArrayList<SPartPack> packs = new <SPartPack> ArrayList();
            ExecutorService executorService = Executors.newFixedThreadPool(Para.TRDS);
            for (int x = 0; x < Para.TRDS; x++) {
                SPartPack ppp = new SPartPack(
                        cdl,
                        rin.subList((x * size), ((x * size) + size)),
                        hash,
                        dna.length(),
                        kt
                        );
                packs.add(ppp);
                executorService.execute(ppp);
            }
            cdl.await();
            executorService.shutdown();
            for (SPartPack t : packs) {
                reads.addAll(t.pOut);
            }
            rin.removeAll(Collections.singleton(null));

            bin.addAll(reads);
            reads.clear();

            fBins.add(new SB(bin));

            if (Para.GUI) {
                p.dPrgA(ProgBar.UPDATE, startSize - (startSize - (rin.size())));
            } else {
                System.out.print("\r partitioning: " + df.format(100 - (((double) (rin.size()) / (startSize))) * 100) + "%");
            }

        } while (rin.size() > 0);
        if (Para.GUI) {
            p.dPrgA(ProgBar.END, 0);
        } else {
            {
                System.out.println("\n");
            }
        }

        return fBins;
    }
}